﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using BruteForceSerializer.Tests.TestClasses;
using NUnit.Framework;

namespace BruteForceSerializer.Tests
{
    [TestFixture]
    public class test_Performance
    {
		[SetUp]
		public void SetUp()
		{
			TypeResolve.Loader_Net45.AssemblyLoader.ConfigurePlatformBasedAssemblyLoading();
		}

		[Test]
		public void Integrationstest_Performance()
		{
			var sut = new Serializer();
			var obj = new KlasseMitCollections();
				
			var sw = new Stopwatch();
			sw.Start();
			for (int i = 0; i < 10000; i++)
			{
				string serialized = sut.Serialize(obj);
				//var bytes = Encoding.UTF8.GetBytes(serialized);
				//Console.WriteLine(serialized);
				var obj2 = sut.DeSerialize(serialized);
				//Assert.IsNotNull(obj2);
			}
			sw.Stop();
			Console.WriteLine("Time needed: " + sw.ElapsedMilliseconds + " ms");
		}


		[Test]
		public void ReflectionOfField()
		{
			//var sut = new Serializer();
			var obj = new KlasseMitCollections();
			
			var sw = new Stopwatch();
			sw.Start();
			for (int i = 0; i < 100000; i++)
			{

				obj.GetType().GetField("StrList").GetValue(obj);
			}
			sw.Stop();
			Console.WriteLine("GetField always + GetValue always: " + sw.ElapsedMilliseconds + " ms");

			sw.Reset();
			sw.Start();
			var fieldsList = obj.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public);
			for (int i = 0; i < 100000; i++)
			{

				fieldsList.First(f => f.Name == "StrList").GetValue(obj);
			}
			sw.Stop();
			Console.WriteLine("GetFields once + Choose Field from List always + GetValue always: " + sw.ElapsedMilliseconds + " ms");

			sw.Reset();
			sw.Start();
			var fieldsDict = obj.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public).ToDictionary(f => f.Name, f => f);
			for (int i = 0; i < 100000; i++)
			{
				//if (fieldsDict.ContainsKey("StrList"))
					fieldsDict["StrList"].GetValue(obj);
			}
			sw.Stop();
			Console.WriteLine("GetFields once + Choose Field from Dictionary always + GetValue always: " + sw.ElapsedMilliseconds + " ms");

			sw.Reset();
			sw.Start();
			var field = obj.GetType().GetField("StrList");
			for (int i = 0; i < 100000; i++)
			{

				field.GetValue(obj);
			}
			sw.Stop();
			Console.WriteLine("GetField once + GetValue always: " + sw.ElapsedMilliseconds + " ms");

			sw.Reset();
			sw.Start();
			var param = Expression.Parameter(typeof (KlasseMitCollections), "x");
			var fieldExpr = Expression.Convert(Expression.Field(param, "StrList"), typeof(object));
            var func = Expression.Lambda<Func<KlasseMitCollections, object>>(fieldExpr, param).Compile();
			for (int i = 0; i < 100000; i++)
			{
				func(obj);
			}
			sw.Stop();
			Console.WriteLine("Expression generation + field access over expression: " + sw.ElapsedMilliseconds + " ms");
		}
    }
}